﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using ATEC.ATDataCoreNET;
using ATEC.ATDataCoreNET.ATObjects;
using ATEC.GeometryNET;
using ATEC.ATCore;
using SSDPNET;
using DynamicButtons;
namespace MaterialExample
{
    public class MaterialMethod
    {

        private static string levelNameRed = "Red";
        private static string levelNameBlue = "Blue";
        /// <summary>
        /// 方法名：CreateObject
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/对象创建
        /// 
        /// 功能：创建两个示例图形对象，分别位于不同图层并具有不同颜色
        /// 返回值：XShapeObject，创建的图形对象
        /// 
        /// 创建流程：
        /// 1. 创建图层：
        ///    - 红色图层（levelNameRed）
        ///    - 蓝色图层（levelNameBlue）
        /// 
        /// 2. 创建第一个对象：
        ///    - 定义四个顶点形成矩形
        ///    - 创建XShapeObject
        ///    - 设置红色图层属性
        /// 
        /// 3. 创建第二个对象：
        ///    - 定义新的四个顶点
        ///    - 创建XShapeObject
        ///    - 设置蓝色图层属性
        /// 
        /// 注意事项：
        /// 1. 确保图层创建成功
        /// 2. 验证点坐标的正确性
        /// 3. 检查对象是否正确添加到场景
        /// </summary>
        private static XShapeObject CreateObject()
        {
            CreateLevelByName(levelNameRed);
            CreateLevelByName(levelNameBlue);
            XPoint3d pt1 = XPoint3d.FromXYZ(-100000, 100000, 0);
            XPoint3d pt2 = XPoint3d.FromXYZ(-100000, -100000, 0);
            XPoint3d pt3 = XPoint3d.FromXYZ(100000, -100000, 0);
            XPoint3d pt4 = XPoint3d.FromXYZ(100000, 100000, 0);
            XPoint3d[] points = { pt1, pt2, pt3, pt4, pt1 };
            ATSceneRef sceneref = SSDPNET.ScenesFunctions.SceneRefGetActive();
            ATProject project = sceneref.GetATProject();
            ATScene scene = sceneref.GetATScene();
            XShapeObject shapeObject = new XShapeObject(scene, null, points);
            SetObjectLevelInfo(shapeObject, levelNameRed);
            shapeObject.AddToScene();

            XPoint3d pt5 = XPoint3d.FromXYZ(200000, 400000, 0);
            XPoint3d pt6 = XPoint3d.FromXYZ(200000, 200000, 0);
            XPoint3d pt7 = XPoint3d.FromXYZ(400000, 200000, 0);
            XPoint3d pt8 = XPoint3d.FromXYZ(400000, 400000, 0);
            XPoint3d[] points2 = { pt5, pt6, pt7, pt8, pt5 };

            XShapeObject shapeObject2 = new XShapeObject(scene, null, points2);
            SetObjectLevelInfo(shapeObject2, levelNameBlue);
            shapeObject2.AddToScene();

            return null;
        }

        /// <summary>
        /// 方法名：findMat
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/材质查找
        /// 
        /// 功能：在指定材质库中查找特定名称的材质
        /// 
        /// 参数：
        /// - materialname：材质名称
        /// - paletteInfoName：材质库名称
        /// 
        /// 返回值：Material，找到的材质对象
        /// 
        /// 查找流程：
        /// 1. 获取材质库列表：
        ///    - 使用MaterialManager获取所有Palette
        ///    - 筛选AT类型的材质库
        /// 
        /// 2. 遍历材质库：
        ///    - 检查材质库名称匹配
        ///    - 获取库中所有材质
        ///    - 查找指定名称的材质
        /// 
        /// 3. 材质匹配：
        ///    - 创建新的Material实例
        ///    - 比对材质名称
        ///    - 返回匹配的材质
        /// 
        /// 错误处理：
        /// - 检查材质搜索状态
        /// - 验证材质库类型
        /// - 处理未找到材质的情况
        /// 
        /// 注意事项：
        /// 1. 材质名称区分大小写
        /// 2. 确保材质库正确加载
        /// 3. 注意材质实例的生命周期
        /// </summary>
        private static Material findMat(string materialname, string paletteInfoName)
        {
            ATSceneRef sceneref = SSDPNET.ScenesFunctions.SceneRefGetActive();
            ATProject project = sceneref.GetATProject();
            //获取所有Palette信息   混凝土  沥青  石材  木材  等
            PaletteInfo[] paletteList = MaterialManager.GetPalettesInATLib(project);
            for (int i = 0; i < paletteList.Length; i++)
            {
                if (PaletteInfo.PaletteType.AT != paletteList[i].Type)
                    continue;

                MaterialSearchStatus tmpSearchStatus = MaterialSearchStatus.NotFound;
                //根据PaletteInfo获取材质    如：获取混凝土下面得材质1，材质2，材质3......
                Material[] materials = MaterialManager.FindMaterialsInPalette(out tmpSearchStatus, paletteList[i], sceneref, false);
                if (MaterialSearchStatus.Success != tmpSearchStatus)
                    continue;
                PaletteInfo paletteInfo = paletteList[i];
                if (paletteInfoName != paletteInfo.Name)
                    continue;
                for (int j = 0; j < materials.Length; j++)
                {
                    Material newMaterial = new Material(materials[j], sceneref);
                    if (materialname != newMaterial.Name)
                        continue;
                    Material mat = MaterialManager.FindMaterialInPalette(materialname, paletteInfo, sceneref);
                    return mat;
                }
            }
            return null;
        }
        /// <summary>
        /// 方法名：AttachMaterial
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/材质附加
        /// 
        /// 功能：创建示例对象并提供材质选择界面进行材质附加
        /// 返回值：void
        /// 
        /// 关键类：
        /// - XShapeObject：图形对象类，用于创建和管理基础图形
        /// - MaterialId：材质标识类，用于材质引用和管理
        /// - MaterialPropertiesExtension：材质属性扩展类，处理材质附加
        /// - ButtonsView：材质选择界面类，提供用户交互
        /// 
        /// 处理流程：
        /// 1. 场景准备：
        ///    - 清空现有场景
        ///    - 创建示例图形对象
        /// 
        /// 2. 材质获取：
        ///    - 获取所有材质库信息
        ///    - 检查材质库有效性
        ///    - 遍历获取可用材质
        /// 
        /// 3. 界面构建：
        ///    - 创建材质选择界面
        ///    - 为每个材质创建按钮
        ///    - 设置材质应用回调
        /// 
        /// 注意事项：
        /// 1. 检查材质库配置
        /// 2. 确保对象创建成功
        /// 3. 正确处理材质附加结果
        /// 4. 及时更新视图
        /// </summary>
        public static void AttachMaterial()
        {
            //清空场景
            ClearScene();
            //创建shapeObject
            XPoint3d pt1 = XPoint3d.FromXYZ(-100000, 100000, 0);
            XPoint3d pt2 = XPoint3d.FromXYZ(-100000, -100000, 0);
            XPoint3d pt3 = XPoint3d.FromXYZ(100000, -100000, 0);
            XPoint3d pt4 = XPoint3d.FromXYZ(100000, 100000, 0);
            XPoint3d[] points = { pt1, pt2, pt3, pt4, pt1 };
            ATSceneRef sceneref = SSDPNET.ScenesFunctions.SceneRefGetActive();
            ATProject project = sceneref.GetATProject();
            ATScene scene = sceneref.GetATScene();
            XShapeObject shapeObject = new XShapeObject(scene, null, points);
            shapeObject.AddToScene();
            //获取所有Palette信息   混凝土  沥青  石材  木材  等
            PaletteInfo[] paletteList = MaterialManager.GetPalettesInATLib(project);
            if (paletteList.Length == 0)
            {
                System.Windows.Forms.MessageBox.Show("请检查“编辑->材质->材质管理”中是否添加材质", "提示");
                return;
            }

            ButtonsView v = new ButtonsView();
           
            
            for (int i = 0; i < paletteList.Length; i++)
            {
                if (PaletteInfo.PaletteType.AT != paletteList[i].Type) //判断type
                    continue;

                //遍历该PaletteInfo中的材质, 如：获取混凝土下面得材质1，材质2，材质3......
                MaterialSearchStatus tmpSearchStatus = MaterialSearchStatus.NotFound;
                Material[] materials =
                    MaterialManager.FindMaterialsInPalette(out tmpSearchStatus, paletteList[i], sceneref, false);
                if (MaterialSearchStatus.Success != tmpSearchStatus)
                    continue;
                for (int j = 0; j < materials.Length; j++)
                {
                    string nameStr = paletteList[i].Name + ":" + materials[j].Name;
                    MaterialId materialId = new MaterialId(materials[j].GetObjectId(), materials[j].Name);
                    //将所有的材质加到操作界面上
                    v.AddButton(nameStr, (object sender, RoutedEventArgs e) =>
                       {
                           MaterialPropertiesExtension mExtension =
                           MaterialPropertiesExtension.GetAsMaterialPropertiesExtension(shapeObject);
                           if (null != mExtension && ATECStatus.Success == mExtension.AddMaterialAttachment(materialId))
                           {
                               ATView.ViewUpdateSingle(2);
                           }
                       });
                }
            }
            v.Show();

        }

     
        /// <summary>
        /// 方法名：AttachMaterialByLevel
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/图层材质
        /// 
        /// 功能：按图层批量附加材质
        /// 返回值：void
        /// 
        /// 关键类：
        /// - FileLevelCache：图层缓存类，管理场景中的图层
        /// - LevelHandle：图层句柄类，操作具体图层
        /// - LevelDefinitionMaterial：图层材质定义类，设置图层材质
        /// - ButtonsView：材质选择界面类，提供用户交互
        /// 
        /// 处理流程：
        /// 1. 场景准备：
        ///    - 清空现有场景
        ///    - 创建示例对象和图层
        /// 
        /// 2. 图层处理：
        ///    - 获取目标图层句柄
        ///    - 验证图层有效性
        /// 
        /// 3. 材质选择：
        ///    - 获取可用材质列表
        ///    - 创建材质选择界面
        ///    - 设置材质应用回调
        /// 
        /// 4. 材质应用：
        ///    - 创建图层材质定义
        ///    - 设置图层材质
        ///    - 更新图层缓存
        /// 
        /// 错误处理：
        /// - 检查图层有效性
        /// - 验证材质库状态
        /// - 处理材质应用失败
        /// 
        /// 注意事项：
        /// 1. 确保图层正确创建
        /// 2. 检查材质库配置
        /// 3. 注意图层缓存更新
        /// 4. 及时刷新视图
        /// </summary>
        public static void AttachMaterialByLevel()
        {
            //清空场景
            ClearScene();
           //创建要附加材质的对象
            CreateObject();
           //获取场景
            ATScene scene = Session.Entity.GetActiveATScenes();
            ATProject project = scene.GetATProject();
            //通过图层名获取LevelHandle
            FileLevelCache fileLevelCache = scene.GetFileLevelCache();
            LevelHandle levelHandle = fileLevelCache.GetLevelByName(levelNameBlue);
            if (!levelHandle.IsValid)
            {
                throw new System.Exception("level handle not valid");
            }
            //获取所有Palette信息   混凝土  沥青  石材  木材  等
            PaletteInfo[] paletteList = MaterialManager.GetPalettesInATLib(project);
            if (paletteList.Length == 0)
            {
                System.Windows.Forms.MessageBox.Show("请检查“编辑->材质->材质管理”中是否添加材质", "提示");
                return;
            }

            ButtonsView v = new ButtonsView();
            

            for (int i = 0; i < paletteList.Length; i++)
            {
                if (PaletteInfo.PaletteType.AT != paletteList[i].Type)
                    continue;
                MaterialSearchStatus tmpSearchStatus = MaterialSearchStatus.NotFound;
                //根据PaletteInfo获取材质    如：获取混凝土下面得材质1，材质2，材质3......
                Material[] materials = MaterialManager.FindMaterialsInPalette(out tmpSearchStatus, paletteList[i], scene, false);
                if (MaterialSearchStatus.Success != tmpSearchStatus)
                    continue;
                for (int j = 0; j < materials.Length; j++)
                {       
                    string nameStr = paletteList[i].Name + ":" + materials[j].Name;
                    Material mat = materials[j];
                    //将所有的材质加到操作界面上
                    v.AddButton(nameStr, (object sender, RoutedEventArgs e) =>
                    {            
                        //通过图层将材质附加上去              
                        LevelDefinitionMaterial leveldeMat = new LevelDefinitionMaterial(mat.GetObjectId(), project);
                        var res = levelHandle.GetEditHandle().SetByLevelMaterial(leveldeMat);
                        var res2 = fileLevelCache.Write();
                        //更新
                        ATView.ViewUpdateSingle(2);
                    });
                }
            }
            v.Show();
        }

        /// <summary>
        /// 方法名：DetachLevelMaterial
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/图层材质
        /// 
        /// 功能：清除指定图层上的材质
        /// 返回值：void
        /// 
        /// 关键类：
        /// - FileLevelCache：图层缓存类，管理图层数据
        /// - LevelHandle：图层句柄类，访问具体图层
        /// - LevelDefinitionMaterial：图层材质定义类，用于清除材质
        /// - ATView：视图更新类，刷新显示效果
        /// 
        /// 处理流程：
        /// 1. 图层获取：
        ///    - 获取当前场景
        ///    - 获取图层缓存
        ///    - 获取目标图层句柄
        /// 
        /// 2. 材质清除：
        ///    - 创建空材质定义
        ///    - 应用到目标图层
        ///    - 更新图层缓存
        /// 
        /// 3. 视图更新：
        ///    - 刷新场景显示
        /// 
        /// 注意事项：
        /// 1. 检查图层有效性
        /// 2. 确保缓存更新成功
        /// 3. 及时刷新视图
        /// </summary>
        public static void DetachLevelMaterial()
        {
            ATScene scene = Session.Entity.GetActiveATScenes();
            ATProject project = scene.GetATProject();
            FileLevelCache fileLevelCache = scene.GetFileLevelCache();
            LevelHandle levelHandle = fileLevelCache.GetLevelByName(levelNameBlue);
            if (!levelHandle.IsValid)
            {
                throw new System.Exception("level handle not valid");
            }
            LevelDefinitionMaterial leveldeMat = new LevelDefinitionMaterial((ObjectId)0L, project);
            var res = levelHandle.GetEditHandle().SetByLevelMaterial(leveldeMat);
            var res2 = fileLevelCache.Write();
            //更新
            ATView.ViewUpdateSingle(2);
        }

        /// <summary>
        /// 方法名：CreateLevelByName
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/图层管理
        /// 
        /// 功能：创建指定名称的图层，并设置相应的颜色属性
        /// 
        /// 参数：
        /// - levelName：图层名称，用于确定图层类型和颜色
        /// 
        /// 关键类：
        /// - FileLevelCache：图层缓存类，管理图层集合
        /// - LevelHandle：图层句柄类，检查图层存在性
        /// - EditLevelHandle：图层编辑类，创建新图层
        /// - LevelDefinitionColor：图层颜色定义类，设置图层颜色
        /// 
        /// 处理流程：
        /// 1. 图层检查：
        ///    - 获取当前图层缓存
        ///    - 检查指定名称图层是否存在
        /// 
        /// 2. 图层创建：
        ///    - 创建新的图层
        ///    - 根据名称确定颜色
        ///    - 设置图层颜色属性
        /// 
        /// 颜色定义：
        /// - levelNameRed：红色(3)
        /// - levelNameBlue：蓝色(1)
        /// - 其他：白色(0)
        /// 
        /// 注意事项：
        /// 1. 避免重复创建图层
        /// 2. 确保颜色索引正确
        /// 3. 验证图层创建结果
        /// </summary>
        public static void CreateLevelByName(string levelName)
        {
            ATProject activeProject = ATEC.ATCore.Session.Entity.GetActiveATProject();
            FileLevelCache fileLevelCache = activeProject.GetLevelCache();//获取当前文件所有图层
            LevelHandle level = fileLevelCache.GetLevelByName(levelName);//根据名称获取图层
            if (!level.IsValid)//若图层不存在，则新建图层
            {
                EditLevelHandle edLevel = fileLevelCache.CreateLevel(levelName);
                //设置图层颜色
                LevelDefinitionColor levelColor = new LevelDefinitionColor(0, activeProject);//白色
                if (levelName == levelNameRed)
                    levelColor = new LevelDefinitionColor(3, activeProject);//红色
                else if (levelName == levelNameBlue)
                    levelColor = new LevelDefinitionColor(1, activeProject);//蓝色

                edLevel.SetByLevelColor(levelColor);
            }
        }

        /// <summary>
        /// 方法名：SetObjectLevelInfo
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/图层设置
        /// 
        /// 功能：设置对象的图层信息和颜色属性
        /// 
        /// 参数：
        /// - obj：目标对象
        /// - levelName：图层名称
        /// 
        /// 关键类：
        /// - ATObject：基础对象类，被操作的目标
        /// - FileLevelCache：图层缓存类，获取图层信息
        /// - ObjectPropertiesSetter：对象属性设置器
        /// - LevelHandle：图层句柄类，获取图层ID
        /// 
        /// 处理流程：
        /// 1. 对象验证：
        ///    - 检查对象有效性
        /// 
        /// 2. 图层获取：
        ///    - 获取图层缓存
        ///    - 查找指定图层
        ///    - 验证图层状态
        /// 
        /// 3. 属性设置：
        ///    - 确定颜色索引
        ///    - 创建属性设置器
        ///    - 应用图层和颜色设置
        /// 
        /// 错误处理：
        /// - 检查对象有效性
        /// - 处理图层未找到情况
        /// - 输出错误信息
        /// 
        /// 注意事项：
        /// 1. 确保对象和图层都有效
        /// 2. 正确设置颜色索引
        /// 3. 处理默认图层情况
        /// </summary>
        public static void SetObjectLevelInfo(ATEC.ATDataCoreNET.ATObjects.ATObject obj, string levelName)
        {
            if (!obj.IsValid)
                return;

            FileLevelCache levelCache = obj.ATScene.GetATProject().GetLevelCache();
            LevelHandle level = levelCache.GetLevelByName(levelName);
            if (LevelCacheErrorCode.None != level.Status)
            {
                string error = "未找到图层" + levelName + "已启用默认图层!";
                SSDPNET.ATOutputFuncs.OutputError(error);
                return;
            }
            uint colorIndex = 0;
            if (levelName == levelNameRed)
                colorIndex = 3;
            else if (levelName == levelNameBlue)
                colorIndex = 1;
            ObjectPropertiesSetter eps = new ObjectPropertiesSetter();
            eps.SetLevel(level.LevelId);
            eps.SetColor(colorIndex);
            eps.Apply(obj);
        }

        /// <summary>
        /// 方法名：CreateAndAssignMaterial
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/材质创建
        /// 
        /// 功能：创建新材质并将其附加到对象上
        /// 返回值：void
        /// 
        /// 关键类：
        /// - MaterialInfo：材质信息类，定义材质属性
        /// - MaterialId：材质标识类，用于材质引用
        /// - MaterialUtl：材质工具类，提供创建和附加功能
        /// - XShapeObject：图形对象类，作为材质载体
        /// 
        /// 处理流程：
        /// 1. 场景准备：
        ///    - 清空现有场景
        ///    - 创建示例图形对象
        /// 
        /// 2. 材质创建：
        ///    - 配置MaterialInfo
        ///    - 设置材质名称和类别
        ///    - 指定贴图文件路径
        /// 
        /// 3. 材质应用：
        ///    - 创建新材质
        ///    - 获取材质ID
        ///    - 将材质附加到对象
        /// 
        /// 注意事项：
        /// 1. 确保贴图文件存在
        /// 2. 验证材质创建结果
        /// 3. 检查材质附加状态
        /// 4. 注意材质资源管理
        /// </summary>
        public static void CreateAndAssignMaterial()
        {
            //清空场景
            ClearScene();
            //创建shapeObject
            XPoint3d pt1 = XPoint3d.FromXYZ(-100000, 100000, 0);
            XPoint3d pt2 = XPoint3d.FromXYZ(-100000, -100000, 0);
            XPoint3d pt3 = XPoint3d.FromXYZ(100000, -100000, 0);
            XPoint3d pt4 = XPoint3d.FromXYZ(100000, 100000, 0);
            XPoint3d[] points = { pt1, pt2, pt3, pt4, pt1 };
            ATSceneRef sceneref = SSDPNET.ScenesFunctions.SceneRefGetActive();
            ATProject project = sceneref.GetATProject();
            ATScene scene = sceneref.GetATScene();
            XShapeObject shapeObject = new XShapeObject(scene, null, points);
            shapeObject.AddToScene();
            

            ATEC.ATCoreNET.MaterialInfo materInfo = new ATEC.ATCoreNET.MaterialInfo();
            materInfo.Name = "材质Test";
            materInfo.Category = "PalteTest";
            string rootDir = ConfigurationManager.GetVariable("_ROOTDIR");
            string filePath = rootDir + "ExampleNet\\Material\\碎石2.jpg";
            materInfo.MapFileName = filePath;

            MaterialId matID = new MaterialId("");

            ATEC.ATCoreNET.MaterialUtl.CreateMaterial(ref matID, materInfo, true);//创建材质

            ATEC.ATCoreNET.MaterialUtl.AssignMaterialToObject(shapeObject, matID);//附加材质
        }

        /// <summary>
        /// 方法名：GetMaterialInfo
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/材质操作/材质获取
        /// 
        /// 功能：根据材质名称和材质库获取材质信息
        /// 返回值：void
        /// 
        /// 关键类：
        /// - MaterialId：材质标识类，用于材质引用
        /// - MaterialUtl：材质工具类，提供材质查询功能
        /// - MessageBox：消息框类，显示操作结果
        /// 
        /// 处理流程：
        /// 1. 参数准备：
        ///    - 设置材质名称
        ///    - 设置材质库名称
        /// 
        /// 2. 材质查询：
        ///    - 创建MaterialId实例
        ///    - 通过名称获取材质
        ///    - 验证材质有效性
        /// 
        /// 3. 结果处理：
        ///    - 检查材质获取结果
        ///    - 显示操作状态
        /// 
        /// 注意事项：
        /// 1. 材质名称必须准确匹配
        /// 2. 材质库名称区分大小写
        /// 3. 处理材质未找到的情况
        /// </summary>
        public static void GetMaterialInfo()
        {
            string materName = "材质Test";
            string paleteName = "PalteTest";
            MaterialId matID = new MaterialId("");
            ATEC.ATCoreNET.MaterialUtl.GetMaterialByName(ref matID, paleteName, materName);
            if (matID.IsValid)
            {
                System.Windows.Forms.MessageBox.Show("材质获取成功");
            }
        }
        /// <summary>
        /// 方法名：ClearScene
        /// 分类：玄镜BIM图形平台/C#开发/示例代码/场景操作
        /// 
        /// 功能：清除场景中的所有对象
        /// 返回值：void
        /// 
        /// 关键类：
        /// - ATSceneRef：场景引用类，访问当前场景
        /// - ATScene：场景类，管理场景内容
        /// - SceneObjectsCollection：场景对象集合类，管理场景对象
        /// 
        /// 处理流程：
        /// 1. 场景获取：
        ///    - 获取活动场景引用
        ///    - 获取场景对象
        /// 
        /// 2. 对象清理：
        ///    - 遍历所有场景对象
        ///    - 逐个删除对象
        /// 
        /// 注意事项：
        /// 1. 确保场景引用有效
        /// 2. 清理操作不可撤销
        /// 3. 注意资源释放
        /// </summary>
        public static void ClearScene()
        {
            ATSceneRef sceneref = SSDPNET.ScenesFunctions.SceneRefGetActive();
            ATProject project = sceneref.GetATProject();
            ATScene scene = sceneref.GetATScene();

            SceneObjectsCollection per = scene.GetGraphicObjects();
            foreach (var obj in per)
            {
                obj.DeleteFromScene();
            }
        }

    }

}
